package com.vastcom.sbjwt.rest;

import com.vastcom.sbjwt.common.DeviceProvider;
import com.vastcom.sbjwt.model.User;
import com.vastcom.sbjwt.model.UserTokenState;
import com.vastcom.sbjwt.security.TokenHelper;
import com.vastcom.sbjwt.security.auth.JwtAuthenticationRequest;
import com.vastcom.sbjwt.service.impl.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mobile.device.Device;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.naming.AuthenticationException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Response;
import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping(value = "/auth",produces = MediaType.APPLICATION_JSON_VALUE)
public class AuthenticationController {
    @Autowired
    TokenHelper tokenHelper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private DeviceProvider deviceProvider;

    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public ResponseEntity<?> createAuthenticationToken(
            @RequestBody JwtAuthenticationRequest authenticationRequest,
            HttpServletResponse response,
            Device device
            ) throws AuthenticationException ,IOException{
        final Authentication authentication=authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        authenticationRequest.getUsername(),
                        authenticationRequest.getPassword()
                )
        );
        // Inject into security context
        SecurityContextHolder.getContext().setAuthentication(authentication);
        // token creation

        User user=(User)authentication.getPrincipal();
        String jws=tokenHelper.generateToken(user.getUsername(),device);
        int expiresIn=tokenHelper.getExpiredIn(device);
        return ResponseEntity.ok(new UserTokenState(jws,expiresIn));
    }

    @RequestMapping(value = "/refresh", method=RequestMethod.POST)
    public ResponseEntity<?> refreshAuthenticationToken(
            HttpServletRequest request,
            HttpServletResponse response,
            Principal principal
    ){
        String authToken =tokenHelper.getToken(request);
        Device device=deviceProvider.getCurrentDevice(request);
        if(authToken!=null&&principal!=null){
            String refreshedToken=tokenHelper.refreshToken(authToken,device);
            int expiresIn=tokenHelper.getExpiredIn(device);
            return ResponseEntity.ok(new UserTokenState(refreshedToken,expiresIn));
        }
        else{
            UserTokenState userTokenState=new UserTokenState();
            return ResponseEntity.accepted().body(userTokenState);
        }
    }


    @RequestMapping(value = "/change-password",method = RequestMethod.POST)
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> changePassword(@RequestBody PasswordChange passwordChanger){
                userDetailsService.changePassword(passwordChanger.oldPassword,passwordChanger.newPassword);
    Map<String,String> result=new HashMap<>();
    result.put("result","success");
    return ResponseEntity.accepted().body(result);
            }

            static class PasswordChange{
        public String oldPassword;
        public String newPassword;
            }
}
